import re
import requests
import time
import os
import sys
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import msvcrt

#=====================================重定位print到日志文件=====================================#
class Logger(object):
    def __init__(self, fileN="Default.log"):
        self.terminal = sys.stdout
        self.log = open(fileN, "a+")
 
    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)
        self.flush() #每次写入后刷新到文件中，防止程序意外结束
    def flush(self):
        self.log.flush()
#=====================================重定位print到日志文件=====================================#



#=====================================获取执行过程中控制台内容=====================================#
# 这个函数拿出来单独作为一个程序，command参数填“python xxx.py”即可执行指定程序并获取控制台输出
def RunShellWithReturnCode(command,print_output=True,universal_newlines=True):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=universal_newlines)
    if print_output:
        output_array = []
        while True:
            line = p.stdout.readline()
            if not line:
                break
            print(line.strip("/n"))
            output_array.append(line)
        output ="".join(output_array)
    else:
        output = p.stdout.read()
    p.wait()
    errout = p.stderr.read()
    if print_output and errout:
        print >> sys.stderr, errout
    p.stdout.close()
    p.stderr.close()
    return output, p.returncode
#=====================================获取执行过程中控制台内容=====================================#



#=====================================  获取URL的响应  =====================================#
def get_response(url, header):
    response = requests.get(url, headers = header)
    if response.status_code == 200:
        return response
    else:
        return
#=====================================  获取URL的响应  =====================================#



#=====================================获取每集动画的链接=====================================#
def get_chapter(comic_catalog_url, header):
    html = get_response(comic_catalog_url, header).text
    comic_name = re.findall('<h1>(.*?)</h1>', html)[-1]
    play_list = re.findall('<p class="play-list">(.*?)</p>', html)
    chapter_list = re.findall('<a target="_blank" href="(.*?)">(.*?)<', str(play_list))
    return comic_name, chapter_list
#=====================================获取每集动画的链接=====================================#



#=====================================打开浏览器模拟请求页面=====================================#
def get_selenium_object(url):
    path = r'D:\Program\Python\geckodriver.exe'
    firefox_options = Options() #创建配置对象
    firefox_options.add_argument('--headless')
    firefox_options.add_argument('--disable-gpu')
    firefox_options.add_argument("user-agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36'")
    browser = webdriver.Firefox(executable_path=path,options=firefox_options)
    browser.get(url)
    return browser
#=====================================打开浏览器模拟请求页面=====================================#
    


#=============================解析出跳转播放链接并请求再解析视频链接=============================#   
def get_video_url(chapter_url, header):
    browser = get_selenium_object(chapter_url)
    browser.find_element_by_xpath('/html/body/div[3]/div/div/div/iframe[2]')

    html_video_play = browser.page_source
    regexp_video_play = '<iframe class="zanpiancms-play-iframe" src="(.*?)" scrolling.*?></iframe>'
    url_video_play = re.findall(regexp_video_play, html_video_play, re.S)[-1]
    browser.close()
    
    html_video_download = requests.get(url_video_play, headers = header).content.decode()
    regexp_video_url = "var purl = '(.*?)';"
    video_url = re.findall(regexp_video_url, html_video_download, re.S)[-1]
    return video_url
#=============================解析出跳转播放链接并请求再解析视频链接=============================#



#=============================带延时输入=============================#

def readInput(caption, timeout=10):
    start_time = time.time()
    #sys.stdout.write('%s(%d秒自动默认下载全部):' % (caption,timeout))
    #sys.stdout.flush()
    print('%s(%d秒自动默认下载全部):' % (caption,timeout))
    while True:
        ini=msvcrt.kbhit()
        try:
            if ini:
                chr = msvcrt.getche()
                if ord(chr) == 13:  # enter_key
                    print ('')
                    return 1
                else:
                    print ('')
                    return 0
        except Exception as e:
            pass
        if time.time() - start_time > timeout:
            print ('')
            return 0

#=============================带延时输入=============================#



#=============================判断输入数字的合法性=============================#
def get_range_chapter(comic_name, chapter_num):
    check_flag = 1      # 1表示设置的值不符合，退出程序，0表示设置生效
    print(comic_name + "  总共  " + str(chapter_num) + "  集")
    while True:
        chapter_start = input("想从哪一集开始下载，比如1、2、3...之类：")
        if (not chapter_start.isdigit()) or int(chapter_start) <= 0 or int(chapter_start) > chapter_num+1:
            choice = input("输入不合法，输入'y'重新输入，输入'n'退出")
            if choice == 'y' or choice == 'Y':
                continue
            elif choice == 'n' or choice == 'N':
                return 0, 0, check_flag
            else:
                return 0, 0, check_flag
        
        print("下载集数的范围是：0--" + str(chapter_num - int(chapter_start) + 1))
        chapter_len   = input("想要下载多少集：")
        
        if (not chapter_len.isdigit()) or int(chapter_len) > chapter_num-int(chapter_start)+1:
            choice = input("输入不合法，输入'y'重新输入，输入'n'退出")
            if choice == 'y' or choice == 'Y':
                continue
            elif choice == 'n' or choice == 'N':
                return 0, 0, check_flag
            else:
                return 0, 0, check_flag
        else:
            start = int(chapter_start)
            lenght= int(chapter_len)
            if lenght < 0:
                lenght = 0
            check_flag = 0
            return start, lenght, check_flag                
        
#=============================判断输入数字的合法性=============================#


#==========================================启动下载任务==========================================#    
def download():

    # 爬取的起点时动漫目录页面
    comic_catalog_url = 'http://www.kuaikan66.com/Animation/huiyedaxiaojiexiangrangwogaobaidierji/'
    header = {
        'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36'
    }
    
    # 返回各集链接的列表
    comic_name, chapter_list = get_chapter(comic_catalog_url, header)
    chapter_num = len(chapter_list)
    print("动画列表获取成功")

    # 默认下载或者自定义下载
    setting_flag = readInput("按下回车进入下载设置")

    if setting_flag:
        # 用户有输入，获取下载开始的集数，下载的集数
        start, lenght, check_flag = get_range_chapter(comic_name, chapter_num)
    else:
        # 用户无输入，使用默认设置
        start = 1
        lenght = chapter_num
        check_flag = 0
    
    # 自定义设置不生效或者下载任务长度为0，不下载，直接退出
    if check_flag or lenght == 0:
        return
    
    # 日志信息输出
    current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    print("***********************************************************************")
    print("开始下载--------   动漫名称：<<" + comic_name + ">>第" + str(start) + "--" + str(start+lenght-1) + "集，共 " + str(lenght) + " 集")
    print("开始时间：" + current_time)
    
    if not os.path.exists(comic_name):
        os.mkdir(comic_name)
    
    chapter_url = []
    chapter_name = []
    for i in chapter_list:
        chapter_url.append('http://www.kuaikan66.com/' + i[0])
        chapter_name.append(i[1])
    
    chapter_url.reverse()
    chapter_name.reverse()
    count = 0
    for chapter in chapter_url:
    
        # 限定下载范围
        if count < start -1 and count >= start + lenght - 1:
            count = count + 1
            continue
    
        # 日志信息输出
        current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        print(current_time + " 第 " + str(count + 1) + " 集开始下载......")
    
        video_url = get_video_url(chapter, header)      # 获得这一集动画的视频链接
        video_dir = comic_name + '/' + chapter_name[count] + '.mp4'
        video = requests.get(video_url, headers = header).content
        with open(video_dir, 'wb') as f:
            f.write(video)
            
        # 日志信息输出
        current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
        print(current_time + " 第 " + str(count + 1) + " 集，下载成功！")
            
        count = count + 1
        
    # 日志信息输出
    current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    print("<<" + comic_name + ">>" + "        共 " + str(lenght) + " 集，下载成功！")
    print("结束时间：" + current_time)
    
#==========================================启动下载任务==========================================#



#==========================================启动搜索任务==========================================#
def search():
    search_name = input("你要找啥：")
    url = "http://www.kuaikan66.com/search/"

    headers = {
            'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36'
        }
    params = {"wd":search_name}

    html = requests.get(url, headers = headers, params = params).content.decode()

    regexp_url_and_name = '<h5><a href="(.*?)">(.*?)</a></h5>'
    regexp_types = '<p class="type fn-left"><em>类型：</em><a href=".*?">(.*?)</a>'

    match = re.findall(regexp_url_and_name, html, re.S)
    types = re.findall(regexp_types, html, re.S)

    search_info = []

    for i in match:
        index = match.index(i)
        search_info.append((i[1], types[index], 'http://www.kuaikan66.com'+i[0]))
    
    item_num = len(search_info)
    
    print(" ")
    print("找到 %d 条相关信息" % item_num)
    print(" ")
    
    for i in search_info:
        print("**************************************************************************************************************************")
        print("编号：" + str(search_info.index(i)))
        print("名称：" + i[0])
        print("类型：" + i[1])
        print("链接：" + i[2])
        print("**************************************************************************************************************************")
        print(" ")
        print(" ")
        
        
#==========================================启动搜索任务==========================================#



if __name__ == '__main__':
    
    # 同时将print定向到日志文件
    # sys.stdout = Logger("log.txt")
    
    # 要把Logger日志关了，不然输入延时那块有问题
    
    # 启动下载
    # download()
    
    # 启动搜索
    search()
    
    # setting_flag = readInput("按下回车进入下载设置", timeout=5)
    # print(str(setting_flag))




